/*
 * Copyright (C) 2012 Rothens
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package rpg.maps;

import java.awt.image.BufferedImage;
import java.util.HashMap;
import rpg.gfx.Bitmap;
import rpg.util.ImageUtil;

/**
 * rothens.tarhely.biz
 *
 * @author Rothens
 */
public class Tiles {

    public HashMap<Character, Tile> landscape;
    public HashMap<Character, RoadTile> roads;
    public HashMap<Character, Tile> layer1;
    public HashMap<Character, Tile> layer2;
    public HashMap<Character, AutoTile> autoTiles;
    public Tile naTile;

    public class Tile {

        public char name;
        public boolean passable = true;
        public boolean transparent = true;
        public int precedence = 200;
        public Bitmap bitmap;
        public boolean autoTile = false;

        public Tile(char name) {
            this.name = name;
        }

        public Tile(BufferedImage img, char name) {
            bitmap = new Bitmap(img.getWidth(), img.getHeight());
            this.name = name;
            img.getRGB(0, 0, bitmap.width, bitmap.height, bitmap.pixels, 0, bitmap.width);

        }

        public Tile(BufferedImage img, char name, int row, int col) {
            bitmap = new Bitmap(64, 64);
            this.name = name;
            img.getSubimage(col * 64, row * 64, 64, 64).getRGB(0, 0, bitmap.width, bitmap.height, bitmap.pixels, 0, bitmap.width);;

        }

        public Tile setTransparent(boolean to) {
            transparent = to;
            return this;
        }

        public Tile setPassable(boolean passable) {
            this.passable = passable;
            return this;
        }

        public Tile setPrecedence(int precedence) {
            this.precedence = precedence;
            return this;
        }
        
        public Tile setAutoTile(boolean autoTile){
            this.autoTile = autoTile;
            return this;
        }
    }

    /**
     * This is the "adapting" version of a tile. This is a tile with 33 different tile-pictures.
     */
    public class AutoTile extends Tile {

        Bitmap[] tiles = new Bitmap[32];

        public AutoTile(BufferedImage img, char name) {
            super(name);
            for (int i = 0; i < 32; i++) {
                tiles[i] = ImageUtil.getSubTile(img, i/16, i%16);
            }
            tiles[16] = new Bitmap(64, 64);
        }
        
        public Bitmap getAuto(int i){
            i = Math.min(31, Math.max(i, 0));
            return(tiles[i]);
        }
    }

    public class RoadTile implements Cloneable {

        private Character name;
        public Bitmap[] bitmaps;
        private int state = 0;

        public RoadTile(Character name, BufferedImage bfImg) {
            this.name = name;
            createBitmaps(bfImg);
        }

        public RoadTile(RoadTile from) {
            name = from.name;
            bitmaps = from.bitmaps;
            state = from.state;
        }

        @Override
        public Object clone() throws CloneNotSupportedException {
            return super.clone();
        }

        public int getState() {
            return state;
        }

        public void setState(int state) {
            this.state = state;
        }

        public Character getName() {
            return name;
        }

        private void createBitmaps(BufferedImage bfImg) {
            bitmaps = new Bitmap[16];
            bitmaps[0] = ImageUtil.getSubTile(bfImg, 0, 5); //o
            bitmaps[4] = ImageUtil.getSubTile(bfImg, 0, 0); //[-
            bitmaps[2] = bitmaps[4].rotate();
            bitmaps[1] = bitmaps[2].rotate();
            bitmaps[8] = bitmaps[1].rotate();


            bitmaps[5] = ImageUtil.getSubTile(bfImg, 0, 1); //-
            bitmaps[10] = bitmaps[5].rotate();
            bitmaps[15] = ImageUtil.getSubTile(bfImg, 0, 2); //+
            bitmaps[13] = ImageUtil.getSubTile(bfImg, 0, 3); //T
            bitmaps[14] = bitmaps[13].rotate();
            bitmaps[7] = bitmaps[14].rotate();
            bitmaps[11] = bitmaps[7].rotate();
            bitmaps[9] = ImageUtil.getSubTile(bfImg, 0, 4); //-,
            bitmaps[12] = bitmaps[9].rotate();
            bitmaps[6] = bitmaps[12].rotate();
            bitmaps[3] = bitmaps[6].rotate();
        }
    }

    public void loadTiles() {

        BufferedImage tileSet = ImageUtil.createImageIcon("/res/tileset.png");
        BufferedImage autoTileSet = ImageUtil.createImageIcon("/res/autoTiles.png");

        //used for unknown characters in the map
        naTile = new Tile(tileSet, '%', 1, 2);

        landscape = new HashMap<Character, Tile>();
        landscape.put('g', new Tile(autoTileSet, 'g', 1, 0).setPrecedence(3).setAutoTile(true)); //grass
        landscape.put('~', new Tile(tileSet, '~', 0, 1).setPassable(false).setPrecedence(0)); //water
        landscape.put('d', new Tile(autoTileSet, 'd', 3, 0).setPrecedence(2).setAutoTile(true)); //dirt
        landscape.put('s', new Tile(autoTileSet, 's', 5, 0).setPrecedence(1).setAutoTile(true)); //sand
        landscape.put('l', new Tile(tileSet, 'l', 1, 1).setPassable(false).setPrecedence(0)); //lava

        BufferedImage layer1Set = ImageUtil.createImageIcon("/res/bushes.png");
        layer1 = new HashMap<Character, Tile>();
        layer1.put('1', new Tile(layer1Set, '1', 0, 0).setPassable(false).setTransparent(false));
        layer1.put('2', new Tile(layer1Set, '2', 0, 1).setPassable(false).setTransparent(false));
        layer1.put('3', new Tile(layer1Set, '3', 0, 2).setPassable(false).setTransparent(false));
        layer1.put('4', new Tile(layer1Set, '4', 1, 0).setPassable(false).setTransparent(false));
        layer1.put('5', new Tile(layer1Set, '5', 1, 1).setPassable(false).setTransparent(false));
        layer1.put('6', new Tile(layer1Set, '6', 1, 2).setPassable(false).setTransparent(false));
        layer1.put('7', new Tile(layer1Set, '7', 2, 0).setPassable(false).setTransparent(false));

        layer2 = new HashMap<Character, Tile>();
        layer2.put('1', new Tile(layer1Set, '1', 2, 1));
        layer2.put('2', new Tile(layer1Set, '2', 2, 2));

        BufferedImage road1 = ImageUtil.createImageIcon("/res/road.png");
        roads = new HashMap<Character, RoadTile>();
        roads.put('1', new RoadTile('1', road1));
        
        //BufferedImage at = ImageUtil.createImageIcon("/res/grass_auto.png");
        autoTiles = new HashMap<Character, AutoTile>();
        autoTiles.put('g', new AutoTile(autoTileSet.getSubimage(0, 0, 1024, 128), 'g'));
        autoTiles.put('d', new AutoTile(autoTileSet.getSubimage(0, 128, 1024, 128), 'd'));
        autoTiles.put('s', new AutoTile(autoTileSet.getSubimage(0, 256, 1024, 128), 's'));
        
    }

    /**
     * Get the assigned tile
     *
     * @param c character
     * @return the tile, or water if not found.
     */
    public Tile getTile(char c) {
        return (landscape.get(c) != null) ? landscape.get(c) : naTile;
    }

    /**
     * Get the assigned layer1 element
     *
     * @param c character
     * @return the tile, or null if not found.
     */
    public Tile getLayer1(char c) {
        return layer1.get(c);
    }

    public Tile getLayer2(char c) {
        return layer2.get(c);
    }

    public RoadTile getRoad(char c) {
        return roads.get(c);
    }
}
